/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#ifndef QLUAQOBJECTWRAPPER_P_H
#define QLUAQOBJECTWRAPPER_P_H

#include "qluascriptvalue.h"
#include "qluascriptengine.h"
#include <QObject>
#include <QPointer>
#include "../etc/lua.hpp"
#include "qlualinkedlist_p.h"

namespace QLuaInternal {

class QLuaQObjectWrapper;

class QLuaCachedMetaObject
{
public:
    QLuaCachedMetaObject();
    virtual ~QLuaCachedMetaObject();

    virtual void objectDeleted();

    QLuaInternal::QLinkedListElement<QLuaCachedMetaObject> m_listNode;
    QLuaQObjectWrapper * m_qobjectWrapper;
};

class QLuaMetaPropertyWrapper : public QLuaCachedMetaObject
{
public:
    QLuaMetaPropertyWrapper();
    virtual ~QLuaMetaPropertyWrapper();

    int m_propertyIndex;

    static int dispatch_gc(lua_State * L);
    static QLuaScriptValue create(QLuaQObjectWrapper * q_object,
                                  int propertyIndex);
};

class QLuaMetaMethodWrapper : public QLuaCachedMetaObject
{
public:
    QLuaMetaMethodWrapper();
    virtual ~QLuaMetaMethodWrapper();

    int m_methodIndex;

    static int dispatch_gc(lua_State * L);
    static int dispatch_call(lua_State * L);
    static QLuaScriptValue create(QLuaQObjectWrapper * q_object,
                                  int methodIndex);
};

class QLuaQObjectWrapper
{
public:
    QLuaQObjectWrapper();
    ~QLuaQObjectWrapper();

    QPointer<QObject> m_objectPtr;
    QLuaScriptEngine::ValueOwnership m_ownership;
    QPointer<QLuaScriptEngine> m_engine;
    QLuaInternal::QLinkedListNode m_cachedItems;
    const QMetaObject * m_metaObject;

    static int dispatch_gc(lua_State * L);
    static int dispatch_index(lua_State * L);
    static int dispatch_newindex(lua_State * L);

    static void registerModule(QLuaScriptEngine * engine);

    static QLuaScriptValue newQObject(QLuaScriptEngine * engine,
                                      QObject * q_object,
                                      QLuaScriptEngine::ValueOwnership ownership);

    QLuaScriptValue handle_index(const QLuaScriptValue& wrapper_self,
                     const QLuaScriptValue& self,
                     const QLuaScriptValue& index);

    void handle_newindex(const QLuaScriptValue& wrapper_self,
                         const QLuaScriptValue& self,
                         const QLuaScriptValue& index,
                         const QLuaScriptValue& value);
};

}

Q_DECLARE_METATYPE(QLuaInternal::QLuaMetaPropertyWrapper)
Q_DECLARE_METATYPE(QLuaInternal::QLuaQObjectWrapper)
Q_DECLARE_METATYPE(QLuaInternal::QLuaMetaMethodWrapper)

#endif // QLUAQOBJECTWRAPPER_P_H
